package pyip.lib.javalearn.thread.join;

import pyip.lib.javalearn.Printer;

public class JoinSyncDemo implements Runnable {

    /**
     * t.join 会等到 ThreadTest#run方法退出之后进入(因为她们都会获取JoinTest 线程锁), 而此时JoinTest#run已经结束;
     * 如果把 ThreadTest#run的睡眠时间改为0, 使得t.join(1000)的时间比 JoinTest#run的睡眠时间更短, 那么main将在 JoinTest#run之前结束.
     * @param args
     */
    public static void main(String[] args) {
        Thread t = new Thread(new JoinSyncDemo(), "bejoinThread");
        new ThreadTest(t, 9000, "bejoinThread-locker").start();
        // new ThreadTest(t, 0, "bejoinThread-locker").start();
        t.start();
        try {
            Printer.out.println("main join start", 0);
            // join的意思是等够这么多毫秒, 在线程isAlive的情况下
            // 在ThreadTest(bejoinThread-locker), 结束后, t.join会与 JoinSyncDemo(bejoinThread)竞争锁
            t.join(1000);
            Printer.out.println("main join finish", 0);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void run() {
        String name = Thread.currentThread().getName();
        try {
            Printer.out.println(name + " start", 1);
            for (int i = 0; i < 10; i++) {
                Thread.sleep(0);
                synchronized (Thread.currentThread()) {
                    Thread.sleep(1000);
                    Printer.out.println(name + " notifyAll", 1);
                    // this.join will be notify
                    Thread.currentThread().notifyAll();
                }
            }
            Thread.sleep(2000);
            Printer.out.println(name + " exit", 1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

class ThreadTest extends Thread {

    private Thread thread;
    private int sleepms;

    public ThreadTest(Thread thread, int sleepms) {
        this.thread = thread;
        this.sleepms = sleepms;
    }

    public ThreadTest(Thread thread, int sleepms, String name) {
        this.thread = thread;
        this.sleepms = sleepms;
        setName(name);
    }

    @Override
    public void run() {
        synchronized (thread) {
            String name = Thread.currentThread().getName();
            Printer.out.println(name + " obtain thread lock", 1);
            try {
                Thread.sleep(sleepms);
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
            Printer.out.println(name + " release thread lock", 1);
        }
    }
}
